Skip to content

feat(dashboard): a few tweaks to the AI models page#3315

Merged
ericallam merged 3 commits intomainfrom
feat/ai-models-tweaks
Apr 2, 2026
Merged

feat(dashboard): a few tweaks to the AI models page#3315
ericallam merged 3 commits intomainfrom
feat/ai-models-tweaks

Conversation

@ericallam
Copy link
Copy Markdown
Member

No description provided.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 2, 2026

⚠️ No Changeset found

Latest commit: 54be599

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

Walkthrough

UI and feature-flag related changes across model pages, navigation, server config, and a test. Tabs were relabeled and swapped (the former "Your Usage" → "Metrics"; "Global Metrics" → "Global metrics") with corresponding keyboard-shortcut and tab-state mapping updates. Several UI widgets were removed (the "Total Calls" big-number and the "Calls over time" chart), grid/height layouts adjusted, and the models table lost its "Calls (7d)" column. Server-side changes: removed AI_MODELS_ENABLED from environment schema, removed hasAiModelsAccess flag and its authorization function, and added a global hasAiAccess flag surfaced in organization presenters. One test timeout increased from 15000ms to 30000ms.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Additional notes

  • Verify removal of AI_MODELS_ENABLED and resulting type/schema impacts.
  • Confirm hasAiAccess is correctly computed and merged with org flags; hasAiModelsAccess was removed.
  • Ensure deleted canAccessAiModels calls were removed/updated wherever used.
  • Validate SideMenu visibility now uses featureFlags.hasAiAccess.
  • Check tab mapping/keyboard shortcuts, removed widgets/columns, and responsive layout changes.
  • Confirm test timeout increase is sufficient and intentional.
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is completely empty, missing all required sections including checklist, testing details, changelog, and screenshots. Add a complete description following the template: fill in the issue number, confirm checklist items, describe testing steps, provide a changelog summary, and include relevant screenshots.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: tweaks to the AI models dashboard, covering UI label changes, widget removals, layout adjustments, and feature flag refactoring.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ai-models-tweaks

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

View 4 additional findings in Devin Review.

Open in Devin Review

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/webapp/app/components/navigation/SideMenu.tsx (1)

480-490: Remove redundant nested gate for “Models”.

Line 480 repeats the same guard already applied at Line 462, so this branch can be simplified.

♻️ Proposed simplification
-                {(user.admin || user.isImpersonating || featureFlags.hasAiAccess) && (
-                  <SideMenuItem
-                    name="Models"
-                    icon={CubeIcon}
-                    activeIconColor="text-purple-500"
-                    inactiveIconColor="text-purple-500"
-                    to={v3ModelsPath(organization, project, environment)}
-                    data-action="models"
-                    isCollapsed={isCollapsed}
-                  />
-                )}
+                <SideMenuItem
+                  name="Models"
+                  icon={CubeIcon}
+                  activeIconColor="text-purple-500"
+                  inactiveIconColor="text-purple-500"
+                  to={v3ModelsPath(organization, project, environment)}
+                  data-action="models"
+                  isCollapsed={isCollapsed}
+                />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/components/navigation/SideMenu.tsx` around lines 480 - 490,
The "Models" SideMenuItem is wrapped in a duplicate conditional (user.admin ||
user.isImpersonating || featureFlags.hasAiAccess) that is already applied by the
parent guard; remove the redundant outer conditional and render the SideMenuItem
directly so the component (SideMenuItem name="Models", icon=CubeIcon,
to={v3ModelsPath(organization, project, environment)}, data-action="models",
isCollapsed={isCollapsed}) is not double-guarded.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/webapp/app/components/navigation/SideMenu.tsx`:
- Around line 480-490: The "Models" SideMenuItem is wrapped in a duplicate
conditional (user.admin || user.isImpersonating || featureFlags.hasAiAccess)
that is already applied by the parent guard; remove the redundant outer
conditional and render the SideMenuItem directly so the component (SideMenuItem
name="Models", icon=CubeIcon, to={v3ModelsPath(organization, project,
environment)}, data-action="models", isCollapsed={isCollapsed}) is not
double-guarded.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 30011a20-ad16-48b7-b89d-91bf9f5e7c05

📥 Commits

Reviewing files that changed from the base of the PR and between 0d0ca7e and 54be599.

📒 Files selected for processing (5)
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/env.server.ts
  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/v3/canAccessAiModels.server.ts
  • apps/webapp/app/v3/featureFlags.ts
💤 Files with no reviewable changes (3)
  • apps/webapp/app/v3/featureFlags.ts
  • apps/webapp/app/v3/canAccessAiModels.server.ts
  • apps/webapp/app/env.server.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

**/*.ts: Use typecheck to verify changes in apps and internal packages (apps/*, internal-packages/*), not build - building proves almost nothing about correctness
When writing Trigger.dev tasks, always import from @trigger.dev/sdk. Never use @trigger.dev/sdk/v3 or deprecated client.defineJob
Add crumbs as you write code - mark lines with // @Crumbs or wrap blocks in `// `#region` `@crumbs for agentcrumbs debug tracing, then strip before merge

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
apps/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

When modifying only server components (apps/webapp/, apps/supervisor/, etc.) with no package changes, add a .server-changes/ file instead of a changeset

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
apps/webapp/**/*.server.{ts,tsx}

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

apps/webapp/**/*.server.{ts,tsx}: Environment variables must be accessed via the env export from app/env.server.ts and never use process.env directly
Always use findFirst instead of findUnique in Prisma queries due to implicit DataLoader batching issues and performance concerns

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
apps/webapp/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Use named constants for sentinel/placeholder values instead of raw string literals scattered across comparisons

Files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
apps/webapp/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Only use useCallback/useMemo for context provider values, expensive derived data with external dependencies, or stable refs required by dependency arrays; don't wrap ordinary event handlers or trivial computations

Files:

  • apps/webapp/app/components/navigation/SideMenu.tsx
🧠 Learnings (7)
📚 Learning: 2026-03-26T17:27:09.938Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 3264
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.private-connections._index/route.tsx:176-176
Timestamp: 2026-03-26T17:27:09.938Z
Learning: In `apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.private-connections._index/route.tsx`, the variable `hasPrivateNetworking` is intentionally hardcoded to `true` as a placeholder. Plan-level gating will be wired to actual billing data (e.g., `plan?.v3Subscription?.plan?.limits?.hasPrivateNetworking`) once the billing integration is complete. The route is already guarded at the feature-flag level via `hasPrivateConnections` in the loader. Do not flag this hardcoded value as dead code or a bug until the billing integration is in place.

Applied to files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
📚 Learning: 2025-08-06T14:25:20.438Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2354
File: apps/webapp/app/presenters/v3/RegionsPresenter.server.ts:117-131
Timestamp: 2025-08-06T14:25:20.438Z
Learning: In RegionsPresenter.server.ts, the final sort by name that removes the "default first" ordering is intentional behavior as a way to prefer the default, as clarified by matt-aitken.

Applied to files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/v3/presenters/**/*.server.{ts,tsx} : Organize presenters in the webapp following the pattern `app/v3/presenters/*/*.server.ts` to move complex loader code into classes

Applied to files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
📚 Learning: 2026-03-22T13:26:12.060Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3244
File: apps/webapp/app/components/code/TextEditor.tsx:81-86
Timestamp: 2026-03-22T13:26:12.060Z
Learning: In the triggerdotdev/trigger.dev codebase, do not flag `navigator.clipboard.writeText(...)` calls for `missing-await`/`unhandled-promise` issues. These clipboard writes are intentionally invoked without `await` and without `catch` handlers across the project; keep that behavior consistent when reviewing TypeScript/TSX files (e.g., usages like in `apps/webapp/app/components/code/TextEditor.tsx`).

Applied to files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
📚 Learning: 2026-03-22T19:24:14.403Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3187
File: apps/webapp/app/v3/services/alerts/deliverErrorGroupAlert.server.ts:200-204
Timestamp: 2026-03-22T19:24:14.403Z
Learning: In the triggerdotdev/trigger.dev codebase, webhook URLs are not expected to contain embedded credentials/secrets (e.g., fields like `ProjectAlertWebhookProperties` should only hold credential-free webhook endpoints). During code review, if you see logging or inclusion of raw webhook URLs in error messages, do not automatically treat it as a credential-leak/secrets-in-logs issue by default—first verify the URL does not contain embedded credentials (for example, no username/password in the URL, no obvious secret/token query params or fragments). If the URL is credential-free per this project’s conventions, allow the logging.

Applied to files:

  • apps/webapp/app/presenters/OrganizationsPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
📚 Learning: 2026-03-22T13:45:36.346Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3244
File: apps/webapp/app/components/navigation/SideMenu.tsx:460-489
Timestamp: 2026-03-22T13:45:36.346Z
Learning: In triggerdotdev/trigger.dev, sidebar navigation items (SideMenu.tsx) are intentionally NOT gated behind feature-flag or permission checks at the nav level. Authorization is enforced at the route/loader level instead. Hiding nav items based on access checks is considered confusing UX. This applies to items like "AI Metrics" (v3BuiltInDashboardPath) and other dashboard links — they are always rendered in the sidebar regardless of hasQueryAccess or similar flags.

Applied to files:

  • apps/webapp/app/components/navigation/SideMenu.tsx
📚 Learning: 2026-02-11T16:37:32.429Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/components/primitives/charts/Card.tsx:26-30
Timestamp: 2026-02-11T16:37:32.429Z
Learning: In projects using react-grid-layout, avoid relying on drag-handle class to imply draggability. Ensure drag-handle elements only affect dragging when the parent grid item is configured draggable in the layout; conditionally apply cursor styles based on the draggable prop. This improves correctness and accessibility.

Applied to files:

  • apps/webapp/app/components/navigation/SideMenu.tsx
🔇 Additional comments (1)
apps/webapp/app/presenters/OrganizationsPresenter.server.ts (1)

160-164: Good default-flag wiring for AI access.

Line 162 correctly sources the flag from env and keeps the existing global+org override flow intact.

@ericallam ericallam merged commit f1f1d02 into main Apr 2, 2026
43 checks passed
@ericallam ericallam deleted the feat/ai-models-tweaks branch April 2, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants